#ifndef __THREAD_H__
#define __THREAD_H__

#include<thread>
#include<functional>
#include<memory>
#include<pthread.h>
#include<string>
#include<semaphore.h>   //信号量
#include<stdint.h>
#include<iostream>
#include<atomic>

namespace sylar{

class Semaphore{
public:
    Semaphore(uint32_t count = 0); 
    ~Semaphore();
    void wait();
    void notify();

private:
    Semaphore(const Semaphore&)=delete;
    Semaphore(const Semaphore&&)=delete;
    Semaphore& operator=(const Semaphore&)=delete;

private:
    sem_t m_semaphore;
};

template<class T>
class ScopedLockImpl{
public:
    ScopedLockImpl(T& mutex):m_mutex(mutex){
        m_mutex.lock();
        m_locked = true;
    }
    ~ScopedLockImpl(){
        unlock();
    }
    void unlock(){
        if(m_locked){
            m_mutex.unlock();
            m_locked = false;
        }
    }
    void lock(){
        if(!m_locked){
            m_mutex.lock();
            m_locked = true;
        }
    }
private:
    T& m_mutex;
    bool m_locked;
};

/// 普通锁
class Mutex{
public:
    using Lock = ScopedLockImpl<Mutex>;
    Mutex(){
        pthread_mutex_init(&m_mutex, nullptr);
    }

    ~Mutex(){
        pthread_mutex_destroy(&m_mutex);
    }
    void lock(){
        pthread_mutex_lock(&m_mutex);
    }
    void unlock(){
        pthread_mutex_unlock(&m_mutex);
    }
private:
    pthread_mutex_t m_mutex;
};

template<class T>
class ReadScopedLockImpl{
public:
    ReadScopedLockImpl(T& mutex):m_mutex(mutex){
        m_mutex.rdlock();
        m_locked = true;
    }
    ~ReadScopedLockImpl(){
        unlock();
    }
    void unlock(){
        if(m_locked){
            m_mutex.unlock();
            m_locked = false;
        }
    }
    void lock(){
        if(!m_locked){
            m_mutex.rdlock();
            m_locked = true;
        }
    }
private:
    T& m_mutex;
    bool m_locked;
};

template<class T>
class WriteScopedLockImpl{
public:
    WriteScopedLockImpl(T& mutex):m_mutex(mutex){
        m_mutex.wrlock();
        m_locked = true;
    }
    ~WriteScopedLockImpl(){
        unlock();
    }
    void unlock(){
        if(m_locked){
            m_mutex.unlock();
            m_locked = false;
        }
    }
    void lock(){
        if(!m_locked){
            m_mutex.wrlock();
            m_locked = true;
        }
    }
private:
    T& m_mutex;
    bool m_locked;
};

/// 读写锁
class RWMutex{
public:
    // 读写锁的声明
    using ReadLock = ReadScopedLockImpl<RWMutex>;
    using WriteLock = WriteScopedLockImpl<RWMutex>;

    RWMutex(){
        pthread_rwlock_init(&m_lock, nullptr);
    }
    ~RWMutex(){
        pthread_rwlock_destroy(&m_lock);
    }

    void rdlock(){
        pthread_rwlock_rdlock(&m_lock);
    }

    void wrlock(){
        pthread_rwlock_wrlock(&m_lock);
    }

    void unlock(){
        pthread_rwlock_unlock(&m_lock);
    }
private:
    pthread_rwlock_t m_lock;
};

/// 自旋锁
class Spinlock{
public:
    using Lock = ScopedLockImpl<Spinlock>;
    Spinlock(){
        pthread_spin_init(&m_mutex, 0);
    }

    ~Spinlock(){
        pthread_spin_destroy(&m_mutex);
    }

    void lock(){
        pthread_spin_lock(&m_mutex);
    }

    void unlock(){
        pthread_spin_unlock(&m_mutex);
    }

private:
    pthread_spinlock_t m_mutex;

};

/// 利用原子量实现自旋锁
class CASLock{
public:
    using Lock = ScopedLockImpl<CASLock>;
    CASLock(){
        m_mutex.clear();
    }
    ~CASLock(){
    }
    void lock(){
        // 返回false表示上锁成功
        while(std::atomic_flag_test_and_set_explicit(&m_mutex, std::memory_order_acquire));
    }
    void unlock(){
        std::atomic_flag_clear_explicit(&m_mutex, std::memory_order_release);
    }
private:
    volatile std::atomic_flag m_mutex;
};

class Thread{
public:
    using ptr = std::shared_ptr<Thread>;
    Thread(std::function<void()> cb, const std::string&  name);
    ~Thread();

    pid_t getId() const{ return m_id;}
    const std::string& getName() const{ return m_name;}
    
    void join();
    
    static Thread* GetThis();
    /// 提供给日志
    static const std::string& GetName();
    static void SetName(const std::string& name);
private:
    /**
     * @brief 禁止拷贝
     * 因为互斥量和互斥信号量是不能拷贝的
     */
    Thread(const Thread&) = delete;
    Thread(const Thread&&) = delete;
    Thread& operator=(const Thread&) = delete;

    static void* run(void* arg);

private:
    pid_t m_id = -1;    // 真实的线程id，全局唯一，不同进程内也不相同。
    pthread_t m_thread = 0;
    std::function<void()> m_cb;
    std::string m_name;

    Semaphore m_semaphore;
};

}

#endif